﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using ServBus.ListForm2010.Utility;
using System.Collections;
using ServBus.ListForm2010.Common.XSNOperator;
using ServBus.ListForm2010.License;

namespace ServBus.ListForm2010.Layouts.ListForm2010
{
    public partial class LookupFormGenerator : LayoutsPageBase
    {
        #region Global Variable

        private SPList _mList;
        private string _contentTypeName;
        private License.License _license;
        private string _errorMsg = "";

        #endregion

        #region Control Event

        private void errorLog(Exception ex, bool internalError)
        {
            if (internalError)
            {
                errorPanel.Visible = true;
            }
            else
            {
                LTException.Text = ex.Message;
                LTException.Visible = true;
            }
            ErrorLog.Write("LookupFormGenerator" + "\r\n" + Request.Url + "\r\n" + ex.Message + "\r\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if (!Page.IsPostBack)
                {
                    Activations activations = new Activations(SPContext.Current.Site.WebApplication);
                    if (!activations.IsActivationValid(SPContext.Current.Web, out _errorMsg))
                    {
                        errorLog(new Exception(_errorMsg), false);
                    }
                    else
                    {
                        _license = LicenseContainer.ProductLicense;
                        if (_license.FeatureSet == FeatureSet.Professional)
                        {
                            InitialPage();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                errorLog(ex,true);
            }
        }

        protected void CreatelkpFormButtonClick(object sender, EventArgs e)
        {
            try
            {
                string xsnLocation = "";
                string destFolderUrl;
                Guid siteId = SPContext.Current.Site.ID;

                Guid webId = SPContext.Current.Web.ID;
                Guid listId = new Guid(Request["source"]);

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(siteId))
                    {
                        using (SPWeb web = site.OpenWeb(webId))
                        {
                            web.AllowUnsafeUpdates = true;

                            _mList = web.Lists[listId];
                            string mContentTypeName = Convert.ToString(Request["cType"]);
                            SPContentType mContentType = _mList.ContentTypes[mContentTypeName];
                            _contentTypeName = mContentType.Name;

                            SPList list = web.Lists[listId];
                            SPContentType cType = list.ContentTypes[_contentTypeName];
                            xsnLocation = web.Url + "/" + cType.ResourceFolder.Url + "/template.xsn";

                            bool configItemUpdated = UpdateConfigList(web, Convert.ToString(_mList.ID), Convert.ToString(mContentType.Id));

                            XListInfo mListInfo = new XListInfo();
                            List<XListInfo> sListInfos = new List<XListInfo>();
                            if (!web.GetFile(xsnLocation).Exists)
                            {

                                //display_lb.aspx, edit_lb.aspx, new_lb.aspx
                                destFolderUrl = cType.ResourceFolder.ServerRelativeUrl;
                                string listParameter = "listId=" + list.ID.ToString();
                                string cTypeParameter = "ctypeId=" + cType.Id.ToString();
                                string uploadFileName = Microsoft.SharePoint.Utilities.SPUtility.GetGenericSetupPath(@"TEMPLATE\LAYOUTS\ListForm2010\Template.aspx");
                                FileStream fileStream = File.Open(uploadFileName, FileMode.Open);
                                web.Files.Add(destFolderUrl + "/display_lb.aspx", fileStream, true);
                                cType.DisplayFormUrl = destFolderUrl + "/display_lb.aspx?" + listParameter + "%26" + cTypeParameter;
                                web.Files.Add(destFolderUrl + "/edit_lb.aspx", fileStream, true);
                                cType.EditFormUrl = destFolderUrl + "/edit_lb.aspx?" + listParameter + "%26" + cTypeParameter;
                                web.Files.Add(destFolderUrl + "/new_lb.aspx", fileStream, true);
                                cType.NewFormUrl = destFolderUrl + "/new_lb.aspx?" + listParameter + "%26" + cTypeParameter;

                                RegisterEventReceiver(list);

                                fileStream.Close();
                                cType.Update();
                                list.Update();

                                #region Generate XSN
                                //Create Main ListInfo
                                //Main List
                                mListInfo.GenerateListInfo(list);
                                mListInfo.AddContentTypeInfo(cType);

                                foreach (TreeNode checkedNode in ContentTypeTvw.CheckedNodes)
                                {
                                    if (checkedNode.Parent != null)
                                    {
                                        SPList slist = web.Lists[checkedNode.Parent.Value];
                                        SPContentType scType = slist.ContentTypes[checkedNode.Value];
                                        XListInfo sListInfo = new XListInfo();
                                        sListInfo.GenerateListInfo(slist);
                                        sListInfo.AddContentTypeInfo(scType);
                                        sListInfos.Add(sListInfo);
                                        RegisterLKPEventReceiver(slist);
                                    }
                                }


                                XSNOperator xsnOperator = new XSNOperator
                                {
                                    SiteId = siteId,
                                    WebId = webId,
                                    ListId = list.ID,
                                    CTypeId = cType.Id,
                                    XSNTemplateFolder = Server.MapPath("/_layouts/ListForm2010/xsn_template/"),
                                    G_Site_Url = site.Url,
                                    G_XSN_Url =
                                        site.Url + list.RootFolder.ServerRelativeUrl + "/" + cType.ResourceFolder.Name +
                                        "/template.xsn",
                                    MListInfo = mListInfo,
                                    SListsInfo = sListInfos
                                };

                                xsnOperator.GenerateXSN();
                                UploadFileToFormLib(xsnOperator);
                                #endregion

                            }
                            else
                            {
                                if (configItemUpdated)
                                {

                                    #region Generate XSN
                                    //Create Main ListInfo
                                    //Main List
                                    mListInfo.GenerateListInfo(list);
                                    mListInfo.AddContentTypeInfo(cType);

                                    foreach (TreeNode checkedNode in ContentTypeTvw.CheckedNodes)
                                    {
                                        if (checkedNode.Parent != null)
                                        {
                                            SPList slist = web.Lists[checkedNode.Parent.Value];
                                            SPContentType scType = slist.ContentTypes[checkedNode.Value];
                                            XListInfo sListInfo = new XListInfo();
                                            sListInfo.GenerateListInfo(slist);
                                            sListInfo.AddContentTypeInfo(scType);
                                            sListInfos.Add(sListInfo);
                                            RegisterLKPEventReceiver(slist);
                                        }
                                    }


                                    XSNOperator xsnOperator = new XSNOperator
                                    {
                                        SiteId = siteId,
                                        WebId = webId,
                                        ListId = list.ID,
                                        CTypeId = cType.Id,
                                        XSNTemplateFolder = Server.MapPath("/_layouts/ListForm2010/xsn_template/"),
                                        G_Site_Url = site.Url,
                                        G_XSN_Url =
                                            site.Url + list.RootFolder.ServerRelativeUrl + "/" +
                                            cType.ResourceFolder.Name + "/template.xsn",
                                        MListInfo = mListInfo,
                                        SListsInfo = sListInfos
                                    };

                                    xsnOperator.GenerateXSN();
                                    UploadFileToFormLib(xsnOperator);
                                    #endregion
                                }
                            }
                        }
                    }
                });

                Response.Write("<script type='text/javascript'>var spOpener = new ActiveXObject('SharePoint.OpenXMLDocuments');if (spOpener != null) {var x = spOpener.CustomizeTemplate('" + xsnLocation + "'); }window.frameElement.commitPopup('ok');</script>");

            }
            catch (Exception ex)
            {
                errorLog(ex,true);
            }
        }

        protected void CancelButtonClick(object sender, EventArgs e)
        {
            Response.Write("<script type='text/javascript'>window.frameElement.commitPopup('cancel');</script>");
        }

        #endregion

        #region Private Method

        private void InitialPage()
        {
            //Initial Parameters
            if (string.IsNullOrEmpty(Request["source"])) return;
            Guid siteId = SPContext.Current.Site.ID;
            Guid webId = SPContext.Current.Web.ID;
            Guid listId = new Guid(Request["source"]);
            string cTypeName = Request["cType"];
            //Set lkpFormbl default status
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite site = new SPSite(siteId))
                {
                    using (SPWeb web = site.OpenWeb(webId))
                    {
                        _mList = web.Lists[listId];
                        //TreeNode rootNode = new TreeNode(web.Title);
                        SPContentType mContentType = _mList.ContentTypes[cTypeName];
                        ArrayList sListConfigValue = getConfigItem(web, Convert.ToString(_mList.ID), Convert.ToString(mContentType.Id));
                        foreach (SPList sList in web.Lists)
                        {
                            TreeNode listNode = new TreeNode(sList.Title);

                            bool isChildList = false;
                            foreach (SPContentType sContentType in sList.ContentTypes)
                            {
                                foreach (SPField field in sContentType.Fields)
                                {
                                    if (field is SPFieldLookup)
                                    {
                                        SPFieldLookup lkpFld = field as SPFieldLookup;
                                        if (!string.IsNullOrEmpty(lkpFld.LookupList)
                                            && lkpFld.LookupList.ToLower().Contains(_mList.ID.ToString().ToLower()))
                                        {
                                            TreeNode cTypeNode = new TreeNode(sContentType.Name);

                                            string configValue = Convert.ToString(sList.ID) + ";" + sContentType.Id;
                                            //if (sListConfigValue != null)
                                            //{
                                            if (sListConfigValue.Contains(configValue))
                                            {
                                                cTypeNode.Checked = true;
                                            }
                                            //}
                                            listNode.ChildNodes.Add(cTypeNode);
                                            isChildList = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            //rootNode.ChildNodes.Add(listNode);
                            if (isChildList)
                            {
                                ContentTypeTvw.Nodes.Add(listNode);
                            }
                        }
                        ContentTypeTvw.ShowCheckBoxes = TreeNodeTypes.Leaf;
                        ContentTypeTvw.ExpandDepth = 1;

                    }
                }
            });
        }

        private ArrayList getConfigItem(SPWeb web, string mListID, string mContentTypeID)
        {
            ArrayList sListInfo = new ArrayList();
            if (!string.IsNullOrEmpty(mListID) && !string.IsNullOrEmpty(mContentTypeID))
            {
                try
                {
                    SPList configList = web.Lists[Constants.LookupForm_Config_NAME];
                    SPQuery query = new SPQuery
                    {
                        Query =
                            "<Where><And><Eq><FieldRef Name='Title' /><Value Type='Text'>" + mListID +
                            "</Value></Eq><Eq><FieldRef Name='mContentType' /><Value Type='Text'>" + mContentTypeID +
                            "</Value></Eq></And></Where>"
                    };
                    SPListItemCollection items = configList.GetItems(query);
                    if (items.Count > 0)
                    {
                        string sListValue = Convert.ToString(items[0]["sTitle"]);
                        string sContentTypeValue = Convert.ToString(items[0]["sContentType"]);

                        if (!string.IsNullOrEmpty(sListValue) && !string.IsNullOrEmpty(sContentTypeValue))
                        {
                            if (sListValue.Contains(";"))
                            {
                                string[] sLists = sListValue.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                                string[] sCTs = sContentTypeValue.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                                for (int i = 0; i < sLists.Length; i++)
                                {
                                    sListInfo.Add(sLists[i] + ";" + sCTs[i]);
                                }
                            }
                            else
                            {
                                sListInfo.Add(sListValue + ";" + sContentTypeValue);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            return sListInfo;
        }

        private bool UpdateConfigList(SPWeb web, string mListID, string mContentTypeID)
        {
            bool updated = false;
            string sListValue = "";
            string sContentTypeValue = "";
            foreach (TreeNode checkedNode in ContentTypeTvw.CheckedNodes)
            {
                try
                {
                    if (checkedNode.Parent != null)
                    {
                        SPList sList = web.Lists[checkedNode.Parent.Value];
                        SPContentType sCT = sList.ContentTypes[checkedNode.Value];
                        sListValue += Convert.ToString(sList.ID) + ";";
                        sContentTypeValue += Convert.ToString(sCT.Id) + ";";
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }

            if (!string.IsNullOrEmpty(sListValue) && !string.IsNullOrEmpty(sContentTypeValue))
            {
                try
                {
                    SPList configList = web.Lists[Constants.LookupForm_Config_NAME];
                    SPQuery query = new SPQuery
                    {
                        Query =
                            "<Where><And><Eq><FieldRef Name='Title' /><Value Type='Text'>" + mListID +
                            "</Value></Eq><Eq><FieldRef Name='mContentType' /><Value Type='Text'>" + mContentTypeID +
                            "</Value></Eq></And></Where>"
                    };
                    SPListItemCollection items = configList.GetItems(query);
                    if (items.Count > 0)
                    {
                        SPListItem item = configList.Items[0];
                        string sTitleValueOld = Convert.ToString(item["sTitle"]);
                        string sContentTypeOld = Convert.ToString(item["sContentType"]);
                        if (!(sTitleValueOld.Equals(sListValue) && sContentTypeOld.Equals(sContentTypeValue)))
                        {
                            item["sTitle"] = sListValue;
                            item["sContentType"] = sContentTypeValue;
                            item.Update();
                        }
                        updated = true;
                    }
                    else
                    {
                        SPListItem item = configList.Items.Add();
                        item["Title"] = mListID;
                        item["mContentType"] = mContentTypeID;
                        item["sTitle"] = sListValue;
                        item["sContentType"] = sContentTypeValue;
                        item.Update();
                        updated = true;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            return updated;
        }

        #endregion

        #region GenerateXSN
        
        private void UploadFileToFormLib(XSNOperator p_XSNOperator)
        {
            try
            {
                System.Threading.Thread.Sleep(1000);
                // SPUtility.CreateFolderUnderList(mWeb,mList.Title,"defaultInfoPath");
                string xsnPath = p_XSNOperator.SaveFolder + "\\template\\template.xsn";
                SPSite site = new SPSite(p_XSNOperator.SiteId);
                SPWeb web = site.AllWebs[p_XSNOperator.WebId];
                SPList mlist = web.Lists[p_XSNOperator.ListId];
                SPContentType mCType = mlist.ContentTypes[p_XSNOperator.CTypeId];
                SPUtility.CreateFile(site, web, mlist, mCType.ResourceFolder.Name, "template.xsn", GetXsnFileStream(xsnPath));
            }
            catch (Exception ex)
            {
                LTException.Text = ex.ToString();
                errorPanel.Visible = true;
            }
        }

        private static byte[] GetXsnFileStream(string xsnPath)
        {
            byte[] buf = new byte[100];
            List<byte> bytes = new List<byte>();
            using (FileStream fs = File.Open(xsnPath, FileMode.Open, FileAccess.Read))
            {
                const int offset = 0;
                while ((fs.Read(buf, offset, buf.Length)) > 0)
                {
                    CopyOneStreamToStream(buf, bytes);
                    buf = new byte[100];
                }
            }

            return bytes.ToArray();
        }

        private static void CopyOneStreamToStream(IEnumerable<byte> byte1, ICollection<byte> byte2)
        {
            foreach (byte bt in byte1)
            {
                byte2.Add(bt);
            }
        }
        #endregion

        #region RegisterEventReceiver

        private static void RegisterEventReceiver(SPList list)
        {
            SPEventReceiverDefinition def1 = list.EventReceivers.Add();
            def1.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def1.Class = "ServBus.ListForm2010.SPFieldChangeEvent.SPFieldChangeEvent";
            def1.Type = SPEventReceiverType.FieldAdded;
            def1.Name = "SPFieldChangeEventFieldAdded";
            def1.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def1.SequenceNumber = 1000;
            def1.Update();

            SPEventReceiverDefinition def2 = list.EventReceivers.Add();
            def2.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def2.Class = "ServBus.ListForm2010.SPFieldChangeEvent.SPFieldChangeEvent";
            def2.Type = SPEventReceiverType.FieldUpdated;
            def2.Name = "SPFieldChangeEventFieldUpdated";
            def2.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def2.SequenceNumber = 1000;
            def2.Update();

            SPEventReceiverDefinition def3 = list.EventReceivers.Add();
            def3.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def3.Class = "ServBus.ListForm2010.SPFieldChangeEvent.SPFieldChangeEvent";
            def3.Type = SPEventReceiverType.FieldDeleting;
            def3.Name = "SPFieldChangeEventFieldDeleting";
            def3.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def3.SequenceNumber = 1000;
            def3.Update();
        }

        private static void RegisterLKPEventReceiver(SPList list)
        {
            SPEventReceiverDefinition def1 = list.EventReceivers.Add();
            def1.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def1.Class = "ServBus.ListForm2010.SPFieldChangeEvent.LKPSPFieldChangeEvent";
            def1.Type = SPEventReceiverType.FieldAdded;
            def1.Name = "LKPSPFieldChangeEventFieldAdded";
            def1.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def1.SequenceNumber = 1000;
            def1.Update();

            SPEventReceiverDefinition def2 = list.EventReceivers.Add();
            def2.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def2.Class = "ServBus.ListForm2010.SPFieldChangeEvent.LKPSPFieldChangeEvent";
            def2.Type = SPEventReceiverType.FieldUpdated;
            def2.Name = "LKPSPFieldChangeEventFieldUpdated";
            def2.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def2.SequenceNumber = 1000;
            def2.Update();

            SPEventReceiverDefinition def3 = list.EventReceivers.Add();
            def3.Assembly = "ServBus.ListForm2010, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=df5827f77359eb0a";
            def3.Class = "ServBus.ListForm2010.SPFieldChangeEvent.LKPSPFieldChangeEvent";
            def3.Type = SPEventReceiverType.FieldDeleting;
            def3.Name = "LKPSPFieldChangeEventFieldDeleting";
            def3.Synchronization = SPEventReceiverSynchronization.Synchronous;
            def3.SequenceNumber = 1000;
            def3.Update();
        }

        #endregion
    }
}
